package org.rambadger.command.auth;


import com.google.common.base.Optional;
import com.yammer.dropwizard.auth.AuthenticationException;
import com.yammer.dropwizard.auth.Authenticator;
import org.mongojack.JacksonDBCollection;

/**
 * Checks the database for a login token that matches a supplied key, and returns the {@link AuthUser authentication information} if successful.
 */
public class UserTokenAuthenticator implements Authenticator<String, AuthUser> {
    private final JacksonDBCollection<AuthToken, String> authTokens;
    private final JacksonDBCollection<AuthUser, String> users;

    /**
     * Instantiates a new user token authenticator.
     *
     * @param authTokens wrapped database collection containing the authentication tokens
     * @param users wrapped database collection containing user role information
     */
    public UserTokenAuthenticator(JacksonDBCollection<AuthToken, String> authTokens, JacksonDBCollection<AuthUser, String> users) {
        this.authTokens = authTokens;
        this.users = users;
    }

    /**
     * Checks the database for a login token with the specified key, and returns the user role information if the token is valid.
     * <p>
     *     Currently the only thing that can invalidate an token that is found in the DB is if the token has expired.
     * </p>
     *
     * @param tokenId the key/id of the token to be searched for
     * @return {@link Optional} value containing the authenticated user, if the authentication succeeded
     * @throws AuthenticationException if there was an error during authentication
     */
    @Override
    public Optional<AuthUser> authenticate(String tokenId) throws AuthenticationException {
        if (tokenId == null) return Optional.absent();
        if (tokenId.isEmpty()) return Optional.absent();

        AuthToken token = authTokens.findOneById(tokenId);

        if (token != null) {
            if (!token.isExpired()) {
                AuthUser user = users.findOneById(token.getUsername());
                return Optional.fromNullable(user);
            }
        }
        return Optional.absent();
    }
}
